# !/bin/bash
# description: 
#
# 目录结构
#
#/..../
#└── bin/                  # 功能脚本目录
#    ├── check_expect.sh   # 环境检测和必要检测
#    ├── scp_expect.sh     # 文件分发
#    ├── exec_expect.sh    # 文件赋权和执行
#    └── log_expect.sh     # 根据关键字收集日志（待开发）
#├── deployScript/         # 传输脚本目录
#    └──customdir/         # 服务器配置文件中对应目录
#       ├──script/         # 脚本目录
#       └──scripts.config  # 自定义脚本执行顺序配置文件
#├── rpm                   # expect安装包
#├── autoRun.sh            # 启动脚本
#├── servers.config        # 服务器配置文件
#├── scripts.config        # 全局脚本执行顺序配置文件
#└── logpath.config        # 日志文件路径配置文件（待开发）
#
# 脚本启动示例: sh autoRun.sh ** 或 ./autoRun.sh **


#当前机器IP
HOST=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}'| sed -n '1p')
#脚本所在的目录
CURRPATH=$(cd $(dirname $0); pwd)
BINPATH=$CURRPATH"/bin"
LOG=$CURRPATH"/log"
if [ ! -d $LOG  ]; then
    mkdir -p $LOG 
fi
#服务器列表
unset remotServers

#脚本列表
unset remotScripts

#自定义脚本列表
unset customRemotScripts

#脚本目录名
script_filename="deployScript"
#源文件根目录
src_file=$CURRPATH"/"$script_filename
#目标服务器存储路径
dest_file="/home/admin/" 

# -----------------------------------------------------------------------------------------------------
# 字体显示
bold=$(tput bold)
underline=$(tput sgr 0 1)
reset=$(tput sgr0)

blue=$(tput setf 1)
purple=$(tput setf 3)
red=$(tput setf 4)
yellow=$(tput setf 6)

textbold() { 
 printf "${bold}[INFO]-[$(date "+%Y-%m-%d %H:%M:%S")] %s${reset}\n" "$@"
}
info() {
 printf "${yellow}[INFO]-[$(date "+%Y-%m-%d %H:%M:%S")] %s${reset}\n" "$@"
}
tips() {
 printf "${blue}[INFO]-[$(date "+%Y-%m-%d %H:%M:%S")] %s${reset}\n" "$@"
}
stips() {
 printf "${purple} %s${reset}\n" "$@"
}
error() {
 printf "${red}[ERROR]-[$(date "+%Y-%m-%d %H:%M:%S")] %s${reset}\n" "$@"
}
check_expect=`rpm -qa | grep expect`
# =========================================================================================================================

# 校验expect是否装载 函数
function checkExpect() {
    info "check_expect: "$check_expect
    if [ -z $check_expect  ]; then
		info "expect is not installed, begin intall expect "
		rpm -ivh ${CURRPATH}/rpm/tcl-8.5.13-8.el7.x86_64.rpm
		rpm -ivh ${CURRPATH}/rpm/expect-5.45-14.el7_1.x86_64.rpm
		
	else
	    info "expect is  installed "
	fi   
}

# =========================================================================================================================

# 校验check_expect.sh、scp_expect.sh、exec_expect.sh是否可执行 函数
function checkExpectShell() { 

	if [ -x "$BINPATH/check_expect.sh" ]; then 
		info "check_expect.sh has permission to run"
	else 
	    info "check_expect.sh has no permission to run ,chmod check_expect.sh +x"
		sudo chmod +x $BINPATH/check_expect.sh
	fi
	
	if [ -x "$BINPATH/scp_expect.sh" ]; then 
		info "scp_expect.sh has permission to run"
	else 
	    info "scp_expect.sh has no permission to run ,chmod scp_expect.sh +x"
		sudo chmod +x $BINPATH/scp_expect.sh
	fi
	
	if [ -x "$BINPATH/exec_expect.sh" ]; then 
		info "exec_expect.sh has permission to run"
	else 
	    info "exec_expect.sh has no permission to run ,chmod exec_expect.sh +x"
		sudo chmod +x $BINPATH/exec_expect.sh
	fi
	
}



# =========================================================================================================================

# 校验远程服务器配置连通性 函数
function checkServer() {
    if [ ${#remotServers[@]} -eq 0 ]; then
		readIps
	fi 
    cremotServers=( "${remotServers[@]}" )
	for server in ${cremotServers[@]}
	do
		#要将$a分割开，先存储旧的分隔符
		OLD_IFS="$IFS"
		#设置分隔符
		IFS="," 
		#如下会自动分隔
		arr=($server)	
		#恢复原来的分隔符
		IFS="$OLD_IFS"
		  
		#expect <<-EOF
		#	set timeout 4
		#	spawn ssh ${arr[0]}@${arr[2]}
		#	expect {
		#	 "yes/no" { send "yes\r"; exp_continue }
		#	 "password:" { send "${arr[1]}\r" }
		#	}
		#	expect "]#"
		#	send "cd /home \r"
		#	send "exit \r"
		#	expect "eof"
		#EOF
		#sudo expect $BINPATH/check_expect.sh ${arr[2]} ${arr[0]} ${arr[1]} & >> $LOG"/check-"$(date "+%Y%m%d").log; &开启子线程，相当于开启多线程
		
		path=`echo $src_file"/"${arr[3]}`
		startTime=`date +%Y%m%d-%H:%M:%S`
		startTime_s=`date +%s`
		status=`ping -c6 ${arr[2]} &>/dev/null && echo yes || echo no`
		#tips "$status"
		if [ "$status" == "yes" ]; then
			sudo expect $BINPATH/check_expect.sh ${arr[2]} ${arr[0]} ${arr[1]}  &>/dev/null
			result=$?
		else
		    result=255
		fi
		
		endTime=`date +%Y%m%d-%H:%M:%S`
		endTime_s=`date +%s`
		sumTime=$[ $endTime_s - $startTime_s ]
		
		opinfo=" status :$result , time count is $sumTime (s)";
		errorFile=$LOG"/check-error."$(date "+%Y%m%d").log
		infoFile=$LOG"/check-info."$(date "+%Y%m%d").log
		
		if [ ! -d ${path} ]; then
		   pinfo="path [ ${path} ]  is not exits, ${opinfo}"
		   if [ $result -eq  0 ]; then
		           error "{${arr[0]}@${arr[2]}} is ok, ${pinfo}"
				   error "{${arr[0]}@${arr[2]}} is ok, ${pinfo}"  >> $errorFile
			else		
				if [ $result -eq  127 ]; then
				   error "{${arr[0]}@${arr[2]}} username or password has error,${pinfo}"
				   error "{${arr[0]}@${arr[2]}} username or password has error,${pinfo}"  >> $errorFile
				else 
				   error "{${arr[0]}@${arr[2]}} can not connect, ${pinfo} " 
				   error "{${arr[0]}@${arr[2]}} can not connect, ${pinfo} " >> $errorFile
				fi
			fi
			remotServers=( "${remotServers[@]/$server}" )
		else 
		   pinfo="path [ ${path} ] is ok , ${opinfo}";
		   if [ $result -eq  0 ]; then
		           info "{${arr[0]}@${arr[2]}} is ok, ${pinfo}"
				   info "{${arr[0]}@${arr[2]}} is ok, ${pinfo}" >> $infoFile
			else		
				if [ $result -eq  127 ]; then
				   error "{${arr[0]}@${arr[2]}} username or password has error,${pinfo}"
				   error "{${arr[0]}@${arr[2]}} username or password has error,${pinfo}" >> $errorFile
				else
				   error "{${arr[0]}@${arr[2]}} can not connect, ${pinfo} "
				   error "{${arr[0]}@${arr[2]}} can not connect, ${pinfo} " >> $errorFile
				fi
				remotServers=( "${remotServers[@]/$server}" )
			fi
		fi
			
	done
	
}

# =========================================================================================================================

# 执行远程传输 函数
function sendExect() {
    if [ ! "${1}" ]; then
		readIps
	else
	    checkServer
	fi
    
	if [ ! -d ${src_file} ]; then
		error " ${src_file} Is not a valid path ,please modfiy!!! "
		exit 1
	fi 
	if [ ${#remotScripts[@]} -eq 0 ]; then
		readScripts
	fi	
    sleep 1	
	for server in ${remotServers[@]}
	do
	    #要将$a分割开，先存储旧的分隔符
		OLD_IFS="$IFS"
		#设置分隔符
		IFS="," 
		#如下会自动分隔
		arr=($server)	
		#恢复原来的分隔符
		IFS="$OLD_IFS"
		basePath=$src_file"/"${arr[3]}
		if [ ! -d ${basePath} ]; then
		   error "it is need path [ ${basePath} ] for scp_expect.sh scp to host[ ${arr[2]} ] ，but path is not exits"
		   continue
		fi
		
		#配置文件不存在或为空，目录遍历;
		customConfig=$basePath"/scripts.config"
		scriptPath=$basePath"/script"
		if [ ! -d ${scriptPath} ]; then
		   error "it is need path [ ${scriptPath} ] for scp_expect.sh scp to host[ ${arr[2]} ] ，but path is not exits"
		   continue
		fi
		readCustomScripts $customConfig
		
		if [[ ${#customRemotScripts[@]} -eq 0 ]] && [[ ${#remotScripts[@]} -eq 0 ]]; then 
			
			sudo expect $BINPATH/scp_expect.sh ${arr[2]} ${arr[0]} ${arr[1]} ${scriptPath} $dest_file "dir" & >> $LOG"/scp-"${arr[2]}"-"$(date "+%Y%m%d").log	
			
			if [ $? -eq  0 ]; then
				info "expect scp_expect.sh  ${arr[2]} ${arr[0]} **** $scriptPath $dest_file dir"
			else
				error "exec [expect scp_expect.sh  ${arr[2]} ${arr[0]} **** $scriptPath $dest_file dir] failed ";
				exit 1
			fi
			
						
		else 
		    
			if [ ${#customRemotScripts[@]} -eq 0 ];then
				execScripts=( "${remotScripts[@]}" )
				tips "use global config [$CURRPATH/scripts.config]"
			else 
			    execScripts=( "${customRemotScripts[@]}" )
				tips "use custom config [ $customConfig ]"
			
			fi
			for script in ${execScripts[@]}
			do	
				#要将$a分割开，先存储旧的分隔符
				OLD_IFS="$IFS"
				#设置分隔符
				IFS="," 
				#如下会自动分隔
				sarr=($script)	
				#恢复原来的分隔符
				IFS="$OLD_IFS"
				shPath=${sarr[0]}
				path=${shPath%/*}
				sudo expect $BINPATH/scp_expect.sh ${arr[2]} ${arr[0]} ${arr[1]} ${scriptPath}${sarr[0]} $dest_file$script_filename$path "sh" & >> $LOG"/scp-"${arr[2]}"-"$(date "+%Y%m%d").log
				#sudo expect $BINPATH/scp_expect.sh ${arr[2]} ${arr[0]} ${arr[1]} ${scriptPath}${sarr[0]} $dest_file$script_filename$path "sh" & >> $LOG"/scp-"${arr[2]}"-"$(date "+%Y%m%d").log				
				if [ $? -eq  0 ]; then
					info "expect scp_expect.sh  ${arr[2]} ${arr[0]} **** $scriptPath$script $dest_file$script_filename$path sh"
				else
					error "exec [expect scp_expect.sh  ${arr[2]} ${arr[0]} **** $scriptPath$script $dest_file$script_filename$path sh] failed ";
					exit 1
				fi
				sleep 2
			done 
		fi
		
	done
}

# =========================================================================================================================

# 执行远程远程赋权+执行 函数
function chmodExect() {
    checkServer
    #默认读取一次配置	
	if [ ${#remotScripts[@]} -eq 0 ]; then
		readScripts
	fi
	for server in ${remotServers[@]}
	do
	    #要将$a分割开，先存储旧的分隔符
		OLD_IFS="$IFS"
		#设置分隔符
		IFS="," 
		#如下会自动分隔
		arr=($server)	
		#恢复原来的分隔符
		IFS="$OLD_IFS"
		
		basePath=$src_file"/"${arr[3]}
		if [ ! -d ${basePath} ]; then
		   error "it is need path [ ${basePath} ] for scp_expect.sh scp to host[ ${arr[2]} ] ，but path is not exits"
		   continue
		fi
		
		#有限自定义配置，没有使用全局配置；配置文件不存在或为空，使用目录遍历;
		customConfig=$basePath"/scripts.config"
		scriptPath=$basePath"/script"
		if [ ! -d ${scriptPath} ]; then
		   error "it is need path [ ${scriptPath} ] for scp_expect.sh scp to host[ ${arr[2]} ] ，but path is not exits"
		   continue
		fi
		readCustomScripts $customConfig
		if [[ ${#customRemotScripts[@]} -eq 0 ]] && [[ ${#remotScripts[@]} -eq 0 ]]; then
			if [[ ! "${1}" ]] || [[ "${1}" == "chmod" ]]; then
				
				sudo $BINPATH/exec_expect.sh chmod ${arr[2]} ${arr[0]} ${arr[1]} ${scriptPath} $dest_file$script_filename & >> $LOG"/exec-"${arr[2]}"-"$(date "+%Y%m%d").log
				if [ $? -eq  0 ]; then
					info "sh exec_expect.sh chmod ${arr[2]} ${arr[0]} **** $scriptPath $dest_file$script_filename "
				else
					error "exec [sh exec_expect.sh chmod ${arr[2]} ${arr[0]} **** $scriptPath $dest_file$script_filename] failed ";
					exit 1
				fi
			else
						
				sudo $BINPATH/exec_expect.sh run ${arr[2]} ${arr[0]} ${arr[1]} ${scriptPath} $dest_file$script_filename & >> $LOG"/exec-"${arr[2]}"-"$(date "+%Y%m%d").log
				wait
				if [ $? -eq  0 ]; then
					info "sh exec_expect.sh run ${arr[2]} ${arr[0]} **** $scriptPath $dest_file$script_filename  ${1}"
				else
					error "exec [sh exec_expect.sh run ${arr[2]} ${arr[0]} **** $scriptPath $dest_file$script_filename  ${1}] failed ";
					exit 1
				fi
				#info "sleep 5 "
				#sleep 5
			fi
		else
		    if [ ${#customRemotScripts[@]} -eq 0 ];then
				execScripts=( "${remotScripts[@]}" )
				tips "use global config [$CURRPATH/scripts.config]"
			else 
				execScripts=( "${customRemotScripts[@]}" )
				tips "use custom config [ $customConfig ]"
				
			fi
			for script in ${execScripts[@]}
			do
				#要将$a分割开，先存储旧的分隔符
				OLD_IFS="$IFS"
				#设置分隔符
				IFS="," 
				#如下会自动分隔
				sarr=($script)	
				#恢复原来的分隔符
				IFS="$OLD_IFS"
				if [[ ! "${1}" ]] || [[ "${1}" == "chmod" ]]; then
					
					sudo $BINPATH/exec_expect.sh chmod ${arr[2]} ${arr[0]} ${arr[1]}  ${sarr[0]} $dest_file$script_filename & >> $LOG"/exec-"${arr[2]}"-"$(date "+%Y%m%d").log
					
					if [ $? -eq  0 ]; then
						info "sh exec_expect.sh chmod ${arr[2]} ${arr[0]} **** ${sarr[0]} $dest_file$script_filename "
					else
						error "exec [sh exec_expect.sh chmod ${arr[2]} ${arr[0]} **** ${sarr[0]} $dest_file$script_filename ] failed ";
						exit 1
					fi
					
				else				
					sudo $BINPATH/exec_expect.sh run ${arr[2]} ${arr[0]} ${arr[1]} ${sarr[0]} $dest_file$script_filename & >> $LOG"/exec-"${arr[2]}"-"$(date "+%Y%m%d").log					
					if [ $? -eq  0 ]; then
						info "sh exec_expect.sh run ${arr[2]} ${arr[0]} **** ${sarr[0]} $dest_file$script_filename  ${1}"
					else
						error "exec [sh exec_expect.sh run ${arr[2]} ${arr[0]} **** ${sarr[0]} $dest_file$script_filename  ${1}] failed ";
						exit 1
					fi
					if [ ! ${sarr[1]} ];then 
						sleep ${sarr[1]}
						wait
					fi
					#info "sleep ${sarr[1]} "
					#sleep ${sarr[1]}
				fi
				
				#if [[ ! "${1}" ]] || [[ "${1}" == "chmod" ]]; then
				#	
				#	sudo $CURRPATH/exec_expect.sh chmod ${arr[2]} ${arr[0]} ${arr[1]} $script $dest_file$script_filename & >> $LOG"/exec-"${arr[2]}"-"$(date "+%Y%m%d").log
				#	
				#	if [ $? -eq  0 ]; then
				#		info "sh exec_expect.sh chmod ${arr[2]} ${arr[0]} **** $script $dest_file$script_filename "
				#	else
				#		error "exec [sh exec_expect.sh chmod ${arr[2]} ${arr[0]} **** $script $dest_file$script_filename ] failed ";
				#		exit 1
				#	fi
				#	
				#else				
				#	sudo $CURRPATH/exec_expect.sh run ${arr[2]} ${arr[0]} ${arr[1]} $script $dest_file$script_filename & >> $LOG"/exec-"${arr[2]}"-"$(date "+%Y%m%d").log
				#	sleep 
				#	if [ $? -eq  0 ]; then
				#		info "sh exec_expect.sh run ${arr[2]} ${arr[0]} **** $script $dest_file$script_filename  ${1}"
				#	else
				#		error "exec [sh exec_expect.sh run ${arr[2]} ${arr[0]} **** $script $dest_file$script_filename  ${1}] failed ";
				#		exit 1
				#	fi
				#	
				#fi
			done
		fi      
		
		
	done
}
# =========================================================================================================================

# 执行远程远程赋权+执行 函数
function rmExect() {
    checkServer
    #默认读取一次配置	
	if [ ${#remotScripts[@]} -eq 0 ]; then
		readScripts
	fi
	for server in ${remotServers[@]}
	do
	    #要将$a分割开，先存储旧的分隔符
		OLD_IFS="$IFS"
		#设置分隔符
		IFS="," 
		#如下会自动分隔
		arr=($server)	
		#恢复原来的分隔符
		IFS="$OLD_IFS"
		#有限自定义配置，没有使用全局配置；配置文件不存在或为空，使用目录遍历;
		customConfig=$basePath"/scripts.config"
		customScripts=$(readCustomScripts $customConfig)
		if [[ ${#customScripts[@]} -eq 0 ]] && [[ ${#remotScripts[@]} -eq 0 ]]; then
			if [ ! "${1}" ]; then
				info " sh exec_expect.sh run ${arr[2]} ${arr[0]} **** $src_file $dest_file$script_filename "
				sudo $BINPATH/rm_expect.sh chmod ${arr[2]} ${arr[0]} ${arr[1]} $src_file $dest_file$script_filename  >> $LOG"/exec-"${arr[2]}"-"$(date "+%Y%m%d").log
			    
			else
				info " sh exec_expect.sh chmod ${arr[2]} ${arr[0]} **** $src_file $dest_file$script_filename  ${1}"
				if [ "${1}" == "-r" ]; then
					sudo $BINPATH/exec_expect.sh run ${arr[2]} ${arr[0]} ${arr[1]} $src_file $dest_file$script_filename >> $LOG"/exec-"${arr[2]}"-"$(date "+%Y%m%d").log
				else
					sudo $BINPATH/exec_expect.sh rundet ${arr[2]} ${arr[0]} ${arr[1]} $src_file $dest_file$script_filename >> $LOG"/exec-"${arr[2]}"-"$(date "+%Y%m%d").log
				fi
			fi
		else
		   
			if [ ${#customScripts[@]} -nq 0 ];then
				execScripts=( "${customScripts[@]}" )
			else 
				execScripts=( "${remotScripts[@]}" )
			fi
			for script in ${execScripts[@]}
			do
				if [ ! "${1}" ]; then
					info "sh exec_expect.sh run ${arr[2]} ${arr[0]} **** $script $dest_file$script_filename "
					sudo $BINPATH/exec_expect.sh chmod ${arr[2]} ${arr[0]} ${arr[1]} $script $dest_file$script_filename  >> $LOG"/exec-"${arr[2]}"-"$(date "+%Y%m%d").log
				else
					info "sh exec_expect.sh chmod ${arr[2]} ${arr[0]} **** $script $dest_file$script_filename  ${1}"
					if [ "${1}" == "-r" ]; then
						sudo $BINPATH/exec_expect.sh run ${arr[2]} ${arr[0]} ${arr[1]} $script $dest_file$script_filename >> $LOG"/exec-"${arr[2]}"-"$(date "+%Y%m%d").log
					else
						sudo $BINPATH/exec_expect.sh rundet ${arr[2]} ${arr[0]} ${arr[1]} $script $dest_file$script_filename >> $LOG"/exec-"${arr[2]}"-"$(date "+%Y%m%d").log
					fi
				fi
			done
		fi
		
		
	done
}

# =========================================================================================================================

# 读取配置ip 函数
function readIps() {
	if [  -f $CURRPATH/servers.config ]; then 
		#设置分隔符
		IFS=$'\n' 
		#如下会自动分隔
		remotServers=($(cat $CURRPATH/servers.config)) 
		#恢复原来的分隔符
		IFS="$OLD_IFS"
	else
	    error " $CURRPATH/servers.config is not exiet, please check "
		exit 1
	fi
}

# =========================================================================================================================

# 读取配置脚本 函数
function readScripts() {
    if [  -f $CURRPATH/scripts.config ]; then 
		#设置分隔符
		IFS=$'\n' 
		#如下会自动分隔
		remotScripts=($(cat $CURRPATH/scripts.config)) 
		#恢复原来的分隔符
		IFS="$OLD_IFS"
	else
	    tips " $CURRPATH/scripts.config is not exist "
	fi
}

# =========================================================================================================================

# 读取子目录配置脚本 函数
function readCustomScripts() {
    if [  -f $1 ]; then 
		#设置分隔符
		IFS=$'\n' 
		#如下会自动分隔
		customRemotScripts=($(cat $1)) 
		#恢复原来的分隔符
		IFS="$OLD_IFS"
	else
	    customRemotScripts=()
	    tips " $1 is not exist "
	fi
}
# =========================================================================================================================

# main 函数

case "$1" in
check)
    checkExpect;
	checkExpectShell;
	checkServer;
;;

scpexp)  
    sendExect $2 
;;
scpssh)
    
	  
;;

srmexp)
    sendExect $2 
;;
srmssh)
    rmExect $2
	  
;;
result)
    
	  
;;
srcexp)
    if [[ ! $2 ]]; then
		error "parameter 2 is needed, for example: -e empowerment(chmod) ; -r empowerment(chmod) and run"
		exit 1
	else
		if [[ "$2" != "-e" && "$2" != "-r" ]]; then
			error "parameter 2 is invalid , for example: -e empowerment(chmod) ; -r empowerment(chmod) and run"
			exit 1
		fi
	fi
	chmodExect $2 $3
;;
srcssh)
	chmodExect $2 
;;
*)
stips "parameter matching is wrong, please refer to the following output (参数匹配不对，请参照如下输出："
stips "check -检查 "
stips "scpexp -需密远程传输( 参数2：默认不校验配置(可不填)；-c 校验配置)"
stips "srcexp -需密远程操作( 参数2：赋权 -e；-r 赋权并执行；参数3：默认不校验配置(可不填)；-c 校验配置)："
stips -e "Usage: $0 {check | scpexp | srcexp}"
exit 1
;;
esac
